﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Xml.Serialization;

namespace org.maquech.CEeL.Core {
    public abstract class PersistentObject {
        #region Fields and Properties
        /// <summary>
        /// The object's id number field
        /// </summary>
        protected int id;

        /// <summary>
        /// The object's id number field property
        /// </summary> 
        public int Id {
            get {
                return this.id;
            }
            set {
                this.id = value;
            }
        }

        /// <summary>
        /// Checks if current object is valid.
        /// </summary>
        public abstract bool IsValid {
            get;
        }

        /// <summary>
        /// Warning messages from database operations.
        /// </summary>
        protected List<string> warningMessages = new List<string>( );

        /// <summary>
        /// Warning messages property
        /// </summary>
        public List<string> WarningMessages {
            get {
                return this.warningMessages;
            }
        }

        /// <summary>
        /// Indicates if the instance is recently created or existes on the database
        /// </summary>
        protected bool isNew;

        /// <summary>
        /// Error messages from database operations.
        /// </summary>
        protected List<string> errorMessages = new List<string>( );

        /// <summary>
        /// Error messages property
        /// </summary>
        public List<string> ErrorMessages {
            get {
                return this.errorMessages;
            }
        }

        /// <summary>
        /// Messages from database operations.
        /// </summary>
        protected List<string> messages = new List<string>( );

        /// <summary>
        ///  Messages property
        /// </summary>
        public List<string> Messages {
            get {
                return this.messages;
            }
        }

        /// <summary>
        /// Clears message lists.
        /// </summary>
        protected void ClearMessages ( ) {
            this.errorMessages.Clear( );
            this.messages.Clear( );
            this.warningMessages.Clear( );
            this.validationMessages.Clear( );
        }

        /// <summary>
        /// Validation error messages from database operations.
        /// </summary>
        protected List<string> validationMessages = new List<string>( );

        /// <summary>
        /// Validation error messages property
        /// </summary>
        public List<string> ValidationMessages {
            get {
                return this.validationMessages;
            }
        }

        /// <summary>
        /// List of fields not in the database.
        /// </summary>
        protected List<string> noDBFields = new List<string>( ) { "warningMessages", "errorMessages", "messages", "noDBFields", "noDBProperties", "modifiedDBFields" };

        /// <summary>
        /// List of properties not in database.
        /// </summary>
        protected List<string> noDBProperties = new List<string>( ) { "WarningMessages", "ErrorMessages", "Messages" };

        /// <summary>
        /// Modified fields for update
        /// </summary>
        protected List<string> modifiedDBFields;

        /// <summary>
        /// List of not null fields
        /// </summary>
        protected List<string> notNullDBFields;

        /// <summary>
        /// Fields and validation dictionary
        /// </summary>
        protected Dictionary<string, string> fieldValidations;

        /// <summary>
        /// List of database related fields.
        /// </summary>
        public List<string> DBFieldNames {
            get {
                List<string> dbFieldNames = new List<string>( );
                Type objType = this.GetType( );
                FieldInfo [ ] fieldInfo = objType.GetFields( );
                foreach ( FieldInfo info in fieldInfo ) {
                    if ( !noDBFields.Contains( info.Name ) )
                        dbFieldNames.Add( info.Name );
                }
                return dbFieldNames;
            }
        }

        /// <summary>
        /// List of database related properties.
        /// </summary>
        public List<string> DBPropertyNames {
            get {
                List<string> dbPropertyNames = new List<string>( );
                Type objType = this.GetType( );
                PropertyInfo [ ] propertyInfo = objType.GetProperties( );
                foreach ( PropertyInfo info in propertyInfo ) {
                    if ( !noDBProperties.Contains( info.Name ) )
                        dbPropertyNames.Add( info.Name );
                }
                return dbPropertyNames;
            }
        }
        #endregion


        #region Methods
        /// <summary>
        /// Saves the current object to the database. Same as <code>Save( true)</code>.
        /// </summary>
        /// <returns><code>true</code> if the object was saved successfully, <code>false</code> otherwise.</returns>
        public abstract bool Save ( );

        /// <summary>
        /// Deletes the object from the database.
        /// </summary>
        /// <returns><code>true</code> if the object was deleted successfully, <code>false</code> otherwise.</returns>
        public abstract bool Delete ( );
        #endregion
    }
}
